;import symbols
(import "sys/symbols.inc")

;some simple structure helpers
(defmacro structure (n o &rest b)
	;(structure name offset [body])
	`(progn (defq _e (env) _n ,n _o ,(eval o)) ~b (def _e (sym (cat _n "_size")) _o '_e nil)))
(defun struct (s &rest b)
	;(struct size field ...)
	(each (lambda (_) (def _e (sym (cat _n "_" _)) _o) (setq _o (+ _o s))) b))
(defun offset (&rest b)
	;(offset field ...)
	(apply struct (cat (list 0) b)))
(defun ptr (&rest b)
	;(ptr field ...)
	(setq _o (align _o ptr_size)) (apply struct (cat (list ptr_size) b)))
(defun long (&rest b)
	;(long field ...)
	(setq _o (align _o long_size)) (apply struct (cat (list long_size) b)))
(defun int (&rest b)
	;(int field ...)
	(setq _o (align _o int_size)) (apply struct (cat (list int_size) b)))
(defun short (&rest b)
	;(short field ...)
	(setq _o (align _o short_size)) (apply struct (cat (list short_size) b)))
(defun byte (&rest b)
	;(byte field ...)
	(setq _o (align _o byte_size)) (apply struct (cat (list byte_size) b)))

;system lisp bindings
(ffi mail-declare "sys/mail/lisp_declare" 0)
(ffi mail-enquire "sys/mail/lisp_enquire" 0)
(ffi mail-devices "sys/mail/lisp_devices" 0)
(ffi mail-forget "sys/mail/lisp_forget" 0)
(ffi mail-poll "sys/mail/lisp_poll" 0)
(ffi mail-read "sys/mail/lisp_read" 0)
(ffi mail-select "sys/mail/lisp_select" 0)
(ffi mail-send "sys/mail/lisp_send" 0)
(ffi mail-alloc-mbox "sys/mail/lisp_alloc_mbox" 0)
(ffi mail-free-mbox "sys/mail/lisp_free_mbox" 0)
(ffi pii-read-char "sys/pii/lisp_readchar" 0)
(ffi pii-write-char "sys/pii/lisp_writechar" 0)
(ffi pii-dirlist "sys/pii/lisp_dirlist" 0)
;(ffi pii-remove "sys/pii/lisp_remove" 0)
(ffi task-mailbox "sys/task/lisp_mailbox" 0)
(ffi task-sleep "sys/task/lisp_sleep" 0)
(ffi mem-stats "sys/mem/lisp_stats" 0)

(defun-bind open-child (task mode)
	;(open-child task mode)
	(defq mbox (mail-alloc-mbox))
	(mail-send (cat
			(char 0 long_size)
			(char mbox long_size)
			(char mode long_size)
			task (char 0))
		(logand (task-mailbox) (const (<< -1 32))))
	(defq id (get-long (mail-read mbox) long_size))
	(mail-free-mbox mbox) id)

(defun-bind open-remote (task node mode)
	;(open-remote task node mode)
	(defq mbox (mail-alloc-mbox))
	(mail-send (cat
			(char 0 long_size)
			(char mbox long_size)
			(char mode long_size)
			(elem index tasks) (char 0))
		(<< node 32))
	(defq id (get-long (mail-read mbox) long_size))
	(mail-free-mbox mbox) id)

(defun-bind open-farm (task num mode &optional devices)
	;(open-farm task num mode [devices])
	(defq devices (opt devices (mail-devices)) ids (cap num (array)) mbox (mail-alloc-mbox)
		index -1 center (+ (/ num 2) (length devices) (opt (find (>> (task-mailbox) 32) devices) 0)))
	(while (< (setq index (inc index)) num)
		(mail-send (cat
				(char index long_size)
				(char mbox long_size)
				(char mode long_size)
				task (char 0))
			(<< (elem (% (+ index center) (length devices)) devices) 32)))
	(while (>= (setq index (dec index)) 0)
		(defq msg (mail-read mbox))
		(push ids (get-long msg long_size)))
	(mail-free-mbox mbox) ids)

(defun-bind open-pipe (tasks)
	;(open-pipe tasks)
	(defq devices (mail-devices) ids (cap (length tasks) (array))
		mbox (mail-alloc-mbox) index -1 tail (task-mailbox))
	(while (< (setq index (inc index)) (length tasks))
		(mail-send (cat
				(char index long_size)
				(char mbox long_size)
				(char kn_call_child long_size)
				(elem index tasks) (char 0))
			(logand tail (const (<< -1 32))))
		(defq tail (get-long (mail-read mbox) long_size))
		(push ids tail))
	(mail-free-mbox mbox) ids)
